"""异常处理中间件，统一处理API请求中的异常"""

import logging
import traceback
from fastapi import Request, HTTPException
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import Response
from fastapi.exceptions import RequestValidationError
from pydantic import ValidationError

from backend.middleware.trace_middleware import get_trace_id
from backend.logger_setup import get_logger_with_trace_id

logger = logging.getLogger('middleware.exception')

class ExceptionMiddleware(BaseHTTPMiddleware):
    """异常处理中间件，统一处理所有异常并返回格式化的响应"""
    
    async def dispatch(self, request: Request, call_next) -> Response:
        # 获取trace_id
        trace_id = get_trace_id(request)
        
        # 获取带trace_id的logger
        log = get_logger_with_trace_id(logger, trace_id)
        
        try:
            # 执行请求处理
            response = await call_next(request)
            return response
        except RequestValidationError as e:
            # 处理请求验证错误
            error_detail = self._format_validation_error(e)
            log.warning(f"请求验证错误 [trace_id={trace_id}]: {error_detail}")
            
            return JSONResponse(
                status_code=422,
                content={
                    "error": "Validation Error",
                    "detail": error_detail,
                    "trace_id": trace_id
                }
            )
        except HTTPException as e:
            # 处理FastAPI HTTP异常
            log.warning(f"HTTP异常 [trace_id={trace_id}, status={e.status_code}]: {e.detail}")
            
            return JSONResponse(
                status_code=e.status_code,
                content={
                    "error": "HTTP Error",
                    "detail": str(e.detail),
                    "trace_id": trace_id
                }
            )
        except ValidationError as e:
            # 处理Pydantic验证错误
            error_detail = self._format_validation_error(e)
            log.warning(f"数据验证错误 [trace_id={trace_id}]: {error_detail}")
            
            return JSONResponse(
                status_code=400,
                content={
                    "error": "Data Validation Error",
                    "detail": error_detail,
                    "trace_id": trace_id
                }
            )
        except Exception as e:
            # 处理其他所有异常
            error_message = str(e)
            # 获取完整的堆栈跟踪
            stack_trace = traceback.format_exc()
            
            log.error(f"未捕获异常 [trace_id={trace_id}]: {error_message}\n{stack_trace}")
            
            # 对于生产环境，不返回详细的错误信息
            from backend.common.config import config_manager
            if config_manager.environment == 'production':
                error_detail = "Internal server error. Please try again later."
            else:
                error_detail = error_message
            
            return JSONResponse(
                status_code=500,
                content={
                    "error": "Internal Server Error",
                    "detail": error_detail,
                    "trace_id": trace_id
                }
            )
    
    def _format_validation_error(self, error) -> dict:
        """格式化验证错误信息
        
        Args:
            error: 验证错误对象
            
        Returns:
            格式化后的错误信息字典
        """
        if hasattr(error, 'errors'):
            errors = error.errors()
            # 格式化错误列表
            formatted_errors = []
            for err in errors:
                # 获取字段名，处理嵌套字段
                field = '.'.join([str(loc) for loc in err['loc']])
                formatted_errors.append({
                    "field": field,
                    "message": err['msg'],
                    "type": err['type']
                })
            return {"errors": formatted_errors}
        return {"message": str(error)}

def setup_exception_handlers(app):
    """设置应用的异常处理器
    
    Args:
        app: FastAPI应用实例
    """
    # 注册异常中间件
    app.add_middleware(ExceptionMiddleware)

__all__ = [
    'ExceptionMiddleware',
    'setup_exception_handlers'
]